Fundamental async/await dan Promise di JavaScript

Dokumentasi ini menjelaskan kenapa operasi seperti query database (Prisma) harus memakai async/await.


Kenapa Ada async/await?

JavaScript bersifat single-threaded — hanya bisa mengerjakan satu hal dalam satu waktu. Tapi banyak operasi yang butuh waktu untuk selesai, misalnya:

  • Mengambil data dari database (seperti prisma.role.findMany())
  • Fetch data dari API
  • Membaca file dari disk

Kalau operasi ini dikerjakan secara blocking (menunggu sampai selesai baru lanjut baris berikutnya), seluruh aplikasi akan freeze — tidak bisa memproses hal lain selama menunggu.

Solusinya: operasi seperti itu dibuat asynchronous (tidak blocking). Kodenya "menitip" — "kerjakan ini di belakang layar, beri tahu aku kalau sudah selesai" — sambil JavaScript tetap bisa mengerjakan hal lain.


Kenapa prisma.role.findMany() Butuh Waktu?

Method ini tidak langsung mengambil data dari memori — dia harus:

  1. Buka koneksi ke database MySQL
  2. Kirim query SQL lewat jaringan (walau ke localhost, tetap ada proses network)
  3. Menunggu database memproses query
  4. Menunggu hasilnya dikirim balik

Semua proses ini makan waktu (meski cuma milidetik), dan JavaScript tidak tahu kapan persis itu selesai. Karena itu, method seperti findMany() tidak langsung mengembalikan data — dia mengembalikan sesuatu yang disebut Promise.


Apa Itu Promise?

Promise adalah "tiket janji" — representasi dari nilai yang belum ada sekarang, tapi akan ada nanti. Tanpa await:

const role = prisma.role.findMany()
console.log(role)

Hasilnya bukan array data, tapi:

Promise { <pending> }

Kenapa? Karena baris console.log dijalankan sebelum query database-nya selesai. JavaScript tidak menunggu — dia langsung lanjut ke baris berikutnya sambil query jalan di belakang layar.


Fungsi await — "Tunggu Dulu Sampai Promise-nya Selesai"

await artinya: "jangan lanjut ke baris berikutnya sampai Promise ini benar-benar selesai dan menghasilkan nilai."

const role = await prisma.role.findMany({
  select: {
    idrole: true,
    rolecat_idrolecat: true,
    appmenunew_idappmenunew: true,
  },
  orderBy: { idrole: 'desc' },
})

console.log(role) // sekarang ini beneran array data, bukan Promise

Dengan await, baris console.log baru dijalankan setelah data dari database benar-benar didapat.


Kenapa Harus Ada async di Depan Function-nya?

Ini aturan bahasa: await hanya boleh dipakai di dalam function yang ditandai async. Kalau tidak, akan error.

// ❌ ERROR: await hanya valid di dalam async function
function getRoles() {
  const role = await prisma.role.findMany()
  return role
}
// ✅ BENAR
async function getRoles() {
  const role = await prisma.role.findMany()
  return role
}

Ini juga kenapa di Server Component Next.js, function-nya wajib async:

export default async function RolesPage() {
  const roles = await prisma.role.findMany({
    select: {
      idrole: true,
      rolecat_idrolecat: true,
      appmenunew_idappmenunew: true,
    },
    orderBy: { idrole: 'desc' },
  })
  // ...
}

Kalau async dihapus dari function ini, await di dalamnya akan error saat build.


Analogi Sederhana

Tanpa await Dengan await
Kamu langsung jalan begitu pesan makanan, padahal makanannya belum jadi. Tangan kamu kosong. Kamu berdiri di kasir menunggu sampai makanannya beneran jadi, baru jalan bawa makanan itu.
  • prisma.role.findMany() = "pesan makanan" (mulai proses, butuh waktu)
  • await = "berdiri menunggu sampai jadi"
  • Tanpa await, kamu "pergi" dengan tangan kosong (dapat Promise, bukan data beneran)

Kenapa Tidak Pakai .then() Saja? (Cara Lama)

Sebelum async/await ada, orang memakai .then():

prisma.role.findMany().then((role) => {
  console.log(role)
})

Ini sama fungsinya, tapi async/await membuat kode terlihat seperti berurutan biasa (mirip sinkron), sehingga lebih mudah dibaca — apalagi kalau ada banyak proses async berantai.

Cara lama (.then) — gampang jadi "callback hell" kalau bertingkat:

function getData() {
  prisma.role.findMany().then((roles) => {
    prisma.rolecat.findMany().then((rolecats) => {
      console.log(roles, rolecats)
    })
  })
}

Cara async/await — lebih rapi dan mudah dibaca:

async function getData() {
  const roles = await prisma.role.findMany()
  const rolecats = await prisma.rolecat.findMany()
  console.log(roles, rolecats)
}

Ringkasan

Istilah Fungsi
Promise "Tiket janji" nilai yang belum ada, tapi akan ada nanti
async Menandai function bahwa di dalamnya ada proses yang butuh menunggu (otomatis me-return Promise)
await "Tunggu di sini sampai Promise-nya selesai," baru lanjut baris berikutnya